Skip to content

fix(email): prevent organization invite autolinks#4088

Merged
RSO merged 5 commits into
mainfrom
gamy-yam
Jun 18, 2026
Merged

fix(email): prevent organization invite autolinks#4088
RSO merged 5 commits into
mainfrom
gamy-yam

Conversation

@RSO

@RSO RSO commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Render organization names in team invitation emails with HTML escaping plus autolink neutralization so URL-like names cannot become active links in mail clients.
  • Preserve existing organization-name validation semantics to avoid breaking production organizations with established punctuation and naming formats.
  • Add regression coverage for email rendering hardening and for accepting URL-like organization names at input while neutralizing them at output.

Verification

Not manually verified; no visual UI changes.

Visual Changes

N/A

Reviewer Notes

Prompted by a HackerOne report about URL-like organization names becoming clickable in official team invitation emails. The existing template already escaped HTML, so the fix targets mail-client autolinking rather than raw HTML injection or broad input rejection.

@RSO RSO marked this pull request as ready for review June 18, 2026 09:24
Comment thread apps/web/src/lib/email.ts Outdated
@kilo-code-bot

kilo-code-bot Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Focused security-hardening change to neutralize URL autolinking in organization invite email rendering; implementation is correct, pure, and covered by a regression test.

Files Reviewed (2 files)
  • apps/web/src/lib/email.ts — added renderNonAutolinkedText and applied it to organization_name in sendOrganizationInviteEmail
  • apps/web/src/lib/email.test.ts — new regression test for HTML escaping + autolink neutralization
Verification Notes
  • renderNonAutolinkedText escapes HTML first, then inserts ​ (zero-width space) after each / and .. The & introduced by ​ is intentionally not re-escaped because it is appended after escapeHtml and must render as an HTML entity — correct behavior since the result is wrapped in RawHtml.
  • Traced the regex .replace(/[/.]/g, '$&​') against the test input; output matches the asserted expectation exactly, including the ZWSP inserted into the escaped closing tag (</​b>).
  • Function is pure with no module-scope state, timers, listeners, or retained references — no memory-leak surface introduced.
  • Only caller is sendOrganizationInviteEmail; no other email paths were changed, so existing organization_name renderings elsewhere (OSS invite, etc.) remain as-is. If those templates also surface user-controlled org names, they may warrant the same hardening — flagged here since it is outside this diff.

Reviewed by glm-5.2-20260616 · 119,139 tokens

Review guidance: REVIEW.md from base branch main

@RSO RSO merged commit 058b72f into main Jun 18, 2026
16 checks passed
@RSO RSO deleted the gamy-yam branch June 18, 2026 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants